package com.gitee.wsl.common.chart.render.foreground

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import com.gitee.wsl.android.ui.ext.type.drawLine
import com.gitee.wsl.common.chart.model.PlotDot
import com.gitee.wsl.common.draw.area.Viewport
import com.gitee.wsl.common.chart.render.background.axis.line.DataLineAxis
import com.gitee.wsl.common.chart.render.shape.plot.PlotDotRender.Companion.plotDotRender
import com.gitee.wsl.common.ui.draw.type.DotStyle
import com.gitee.wsl.common.ui.draw.type.LineSpacingStyle
import com.gitee.wsl.common.ui.draw.type.VerticalAlign
import com.gitee.wsl.android.ui.ext.type.drawRotateText
import com.gitee.wsl.android.ui.ext.type.lineHeight
import com.gitee.wsl.android.ui.ext.type.textHeight
import com.gitee.wsl.math.Math
import com.gitee.wsl.jvm.math.add
import com.gitee.wsl.jvm.math.div
import com.gitee.wsl.jvm.math.getLnPlotXValPosition
import com.gitee.wsl.jvm.math.mul
import com.gitee.wsl.jvm.math.sub

import timber.log.Timber

/**
 * @ClassName PlotCustomLine
 * @Description  处理定制线(参考线/分界线)的绘制 <br/>
 *
 * @author XiongChuanLiang<br/>(xcl_168@aliyun.com)
 *
 */

class PlotCustomLine {

    //定制集合
    var customLineDataset = mutableListOf<CustomLineData>()

    var dataAxis: DataLineAxis? = null
    var plotViewport: Viewport? = null
    var axisScreenHeight = 0.0f
    var axisScreenWidth = 0.0f

    val plotDot: PlotDot = PlotDot()

    private fun validateParams(): Boolean {
        if (null == dataAxis) {
            Timber.d( "数据轴基类没有传过来。")
            return false
        }
        if (null == plotViewport) {
            Timber.d( "绘图区基类没有传过来。")
            return false
        }

        //数据集没有传过来
        return true
    }

    fun setVerticalPlot(
        dataAxis: DataLineAxis,
        plotViewport: Viewport, axisScreenHeight: Float
    ) {
        this.dataAxis =dataAxis
        this.plotViewport =plotViewport
        this.axisScreenHeight =axisScreenHeight
    }

    fun setHorizontalPlot(
        dataAxis: DataLineAxis?,
        plotViewport: Viewport?, axisScreenWidth: Float
    ) {
        this.dataAxis =dataAxis
        this.plotViewport =plotViewport
        this.axisScreenWidth =axisScreenWidth
    }


    /**
     * 用来画竖向柱形图，横向的定制线
     * @param canvas 画布
     * @return 是否成功
     */
    fun renderVerticalCustomlinesDataAxis(canvas: Canvas): Boolean {
        if (!validateParams()) return false
        if (0.0f == axisScreenHeight) {
            Timber.d( "轴的屏幕高度值没有传过来。")
            return false
        }
        val axisHeight =  Math.sub(dataAxis!!.axisMax, dataAxis!!.axisMin)
        for (line in customLineDataset) {
            line.customLinePaint.color = line.color
            line.customLinePaint.strokeWidth = line.lineStroke.toFloat()

            //double  postion = mAxisScreenHeight * ( 
            //					(line.getValue() - mDataAxis.getAxisMin()) /axisHeight  );
            val per =  Math.div( Math.sub(line.value, dataAxis!!.axisMin), axisHeight)
            val postion = Math.mul(axisScreenHeight, per)

            //float currentY = (float) (mPlotArea.getBottom() - postion); 			
            val currentY =  Math.sub(plotViewport!!.bottom, postion)

            //绘制线
            if (line.isShowLine)
                canvas.drawLine(line.lineSpacingStyle, plotViewport!!.left, currentY, plotViewport!!.right, currentY, line.customLinePaint)
            //绘制标签和箭头
            drawCapLabelVerticalPlot(canvas, line, postion)
        }
        return true
    }

    /**
     * 用来画横向柱形图，竖向的定制线
     * @param canvas 画布
     * @return 是否成功
     */
    fun renderHorizontalCustomlinesDataAxis(canvas: Canvas): Boolean {
        if (!validateParams()) return false
        if (0.0f == axisScreenWidth) {
            Timber.d("轴的屏幕宽度值没有传过来。")
            return false
        }
        val axisHeight = dataAxis!!.axisMax - dataAxis!!.axisMin
        for (line in customLineDataset) {
            line.customLinePaint.color = line.color
            line.customLinePaint.strokeWidth = line.lineStroke.toFloat()
            val position = axisScreenWidth * ((line.value - dataAxis!!.axisMin) / axisHeight)
            val currentX = plotViewport!!.left + position

            //绘制线
            if (line.isShowLine)
                canvas.drawLine(line.lineSpacingStyle, currentX, plotViewport!!.bottom, currentX, plotViewport!!.top, line.customLinePaint)

            //绘制标签和箭头
            drawCapLabelHorizontalPlot(canvas, line, position)
        }
        return true
    }

    // PlotAreaRender plotArea,
    fun renderCategoryAxisCustomlines(
        canvas: Canvas,
        plotScreenWidth: Float,
        plotViewport: Viewport,
        maxValue: Float, minValue: Float
    ): Boolean {
        this.plotViewport =plotViewport
        for (line in customLineDataset) {
            line.customLinePaint.color = line.color
            line.customLinePaint.strokeWidth = line.lineStroke.toFloat()
            val pos = Math.getLnPlotXValPosition(plotScreenWidth, plotViewport.left, line.value, maxValue, minValue)
            val currentX =  Math.add(plotViewport.left, pos)

            //绘制线
            if (line.isShowLine)
                canvas.drawLine(line.lineSpacingStyle, currentX, plotViewport.bottom, currentX, plotViewport.top, line.customLinePaint)

            //绘制标签和箭头
            drawCapLabelHorizontalPlot(canvas, line, pos)
        }
        return true
    }


    /**
     * 绘制标签和箭头
     * @param canvas    画布
     * @param line        线基类
     * @param chartPostion    位置
     */
    private fun drawCapLabelVerticalPlot(
        canvas: Canvas,
        line: CustomLineData, chartPostion: Float
    ) {
        if (line.label.isNotEmpty()) {
            var currentX = 0.0f
            var currentY = 0.0f
            var capX = 0.0f

            //显示在哪个高度位置
            currentY =  Math.sub(plotViewport!!.bottom, chartPostion)
            when (line.labelHorizontalPostion) {
                Paint.Align.LEFT -> {
                    currentX =  Math.sub(plotViewport!!.left, line.labelOffset)
                    line.lineLabelPaint.textAlign = Paint.Align.RIGHT
                    capX = plotViewport!!.right
                }
                Paint.Align.CENTER -> {
                    //currentX = mPlotArea.getLeft() + 
                    //			(mPlotArea.getRight() -  mPlotArea.getLeft() ) /2  - line.getLabelOffset();		
                    val w =  Math.div( Math.sub(plotViewport!!.right, plotViewport!!.left), 2f)
                    currentX =  Math.add(plotViewport!!.left, w)
                    currentX =  Math.sub(currentX, line.labelOffset)
                    line.lineLabelPaint.textAlign = Paint.Align.CENTER

                    //capX = mPlotArea.getLeft() + (mPlotArea.getRight() -  mPlotArea.getLeft() ) /2;						
                    val w2 =  Math.div( Math.sub(plotViewport!!.right, plotViewport!!.left), 2f)
                    capX =  Math.add(plotViewport!!.left, w2)
                }
                Paint.Align.RIGHT -> {
                    currentX =  Math.add(plotViewport!!.right, line.labelOffset)
                    line.lineLabelPaint.textAlign = Paint.Align.LEFT
                    capX = plotViewport!!.left
                }
            }

            //绘制箭头			
            drawLineCapVerticalPlot(canvas, line, capX, currentY)

            //绘制标签
            drawLabel(canvas, line, currentX, currentY)
        }
    }


    private fun drawLabel(
        canvas: Canvas,
        line: CustomLineData, currentX: Float, currentY1: Float
    ) {
        var currentY = currentY1
        val txtHeight = line.lineLabelPaint.textHeight

        when (line.labelHorizontalPostion) {
            Paint.Align.LEFT -> currentY += txtHeight / 3
            Paint.Align.CENTER -> if (line.isShowLine) currentY -= line.customLinePaint.lineHeight
            Paint.Align.RIGHT -> currentY += txtHeight / 3
        }

        //绘制标签				
        canvas.drawRotateText(
            line.label,
            currentX, currentY,
            line.labelRotateAngle,
             line.lineLabelPaint
        )
    }


    /**
     * 绘制标签和箭头
     * @param canvas    画布
     * @param line        线基类
     * @param chartPostion    位置
     */
    private fun drawCapLabelHorizontalPlot(
        canvas: Canvas,
        line: CustomLineData, chartPostion: Float
    ) {
        if (line.label.isNotEmpty()) {
            var currentX = 0.0f
            var currentY = 0.0f
            var capY = 0.0f
            currentX = plotViewport!!.left + chartPostion
            when (line.labelVerticalAlign) {
                VerticalAlign.TOP -> {
                    currentY = plotViewport!!.top - line.labelOffset
                    capY = plotViewport!!.bottom
                }
                VerticalAlign.MIDDLE -> {
                    currentY = plotViewport!!.bottom - (plotViewport!!.bottom - plotViewport!!.top) / 2 - line.labelOffset
                    capY = plotViewport!!.bottom - (plotViewport!!.bottom - plotViewport!!.top) / 2
                }
                VerticalAlign.BOTTOM -> {
                    currentY = plotViewport!!.bottom + line.labelOffset
                    capY = plotViewport!!.top
                }
            }
            line.lineLabelPaint.textAlign = Paint.Align.CENTER

            //绘制箭头			
            drawLineCapHorizontalPlot(canvas, line, currentX, capY)

            //绘制标签		
            canvas.drawRotateText(
                line.label, currentX, currentY,
                line.labelRotateAngle,
                 line.lineLabelPaint
            )
        }
    }

    //绘制箭头
    private fun drawLineCapHorizontalPlot(
        canvas: Canvas,
        line: CustomLineData, currentX: Float, currentY: Float
    ) {
        drawLineCap(canvas, line, currentX, currentY, currentX, currentY)
    }


    //绘制箭头
    private fun drawLineCapVerticalPlot(
        canvas: Canvas,
        line: CustomLineData, currentX: Float, currentY: Float
    ) {
        val left = currentX - CAPSIZE * 2
        val top = currentY - CAPSIZE * 2
        drawLineCap(canvas, line, left, top, currentX, currentY)
    }

    //绘制箭头
    private fun drawLineCap(
        canvas: Canvas, line: CustomLineData,
        left: Float, top: Float, right: Float, bottom: Float
    ) {
        plotDot.dotStyle = line.customeLineCap
        plotDotRender.renderDot(
            canvas, plotDot,left + (right - left) / 2, top + (bottom - top) / 2, line.customLinePaint
        ) //标识图形          	
    }


    companion object{
        //默认箭头大小
        private const val CAPSIZE = 10
    }
}

/**
 * @ClassName CustomLineData
 * @Description 定制线基类用于强调标准,底线之类,也可用于显示计算出来的平均线之类
 * @author XiongChuanLiang<br/>(xcl_168@aliyun.com)
 *
 */
class CustomLineData(){
    var label = ""
    var value = 0.0f
    var color = Color.BLACK
    var lineStroke = 0

    //文字旋转角度
    var labelRotateAngle = 0.0f //-45f;
    
    //设置Label显示位置(左，中，右)
    var labelHorizontalPostion = Paint.Align.RIGHT

    //设置Label显示位置(上，中，下)
    var labelVerticalAlign = VerticalAlign.TOP
    
    //线的风格(点或线之类)
    var lineSpacingStyle = LineSpacingStyle.Solid

    //设置线箭头 (三角，方形，棱形....)  
    var customeLineCap = DotStyle.HIDE

    //标签偏移距离,注意，如是显示在中间，则会上移动此距离。
    var labelOffset = 0f

    constructor( label:String,
                  value :Float,
                  color :Int,
                  lineStroke :Int):this(){

       this.label=label
       this.value=value
       this.color=color
       this.lineStroke=lineStroke
    }

    //定制线画笔
    val customLinePaint: Paint by lazy {
        Paint().apply {
            isAntiAlias = true
            strokeWidth = 3f
            textSize = 18f
            textAlign = Paint.Align.LEFT
        }
    }
    
    val lineLabelPaint: Paint by lazy {
        Paint().apply {
            isAntiAlias = true
            strokeWidth = 3f
            textSize = 18f
            textAlign = Paint.Align.LEFT
        }
    }

    //是否显示线
    var isShowLine = true
}